import { HubConnection, HubConnectionBuilder, LogLevel } from '@microsoft/signalr'
import type { Message, SendMessageRequest } from '@/types'

class SignalRService {
  private connection: HubConnection | null = null
  private isConnecting = false
  private reconnectAttempts = 0
  private maxReconnectAttempts = 5
  private reconnectDelay = 1000

  async connect(token: string): Promise<void> {
    // 如果已经连接，直接返回
    if (this.connection?.state === 'Connected') {
      return
    }

    // 如果正在连接，等待连接完成
    if (this.isConnecting) {
      return new Promise((resolve, reject) => {
        const checkConnection = () => {
          if (!this.isConnecting) {
            if (this.connection?.state === 'Connected') {
              resolve()
            } else {
              reject(new Error('连接失败'))
            }
          } else {
            setTimeout(checkConnection, 100)
          }
        }
        checkConnection()
      })
    }

    this.isConnecting = true

    try {
      // 如果存在旧连接，先断开
      if (this.connection) {
        await this.connection.stop()
        this.connection = null
      }

      this.connection = new HubConnectionBuilder()
        .withUrl(`${import.meta.env.VITE_API_BASE_URL?.replace('/api', '') || 'http://localhost:5276'}/chathub`, {
          accessTokenFactory: () => token
        })
        .withAutomaticReconnect({
          nextRetryDelayInMilliseconds: (retryContext) => {
            if (retryContext.previousRetryCount < this.maxReconnectAttempts) {
              return this.reconnectDelay * Math.pow(2, retryContext.previousRetryCount)
            }
            return null // 停止重连
          }
        })
        .configureLogging(LogLevel.Information)
        .build()

      // 设置事件监听器
      this.setupEventListeners()

      await this.connection.start()
      console.log('SignalR连接已建立')
      this.reconnectAttempts = 0
      this.notifyConnectionStateChanged()
    } catch (error) {
      console.error('SignalR连接失败:', error)
      this.connection = null
      throw error
    } finally {
      this.isConnecting = false
    }
  }

  async disconnect(): Promise<void> {
    if (this.connection) {
      await this.connection.stop()
      this.connection = null
      console.log('SignalR连接已断开')
    }
  }

  private setupEventListeners(): void {
    if (!this.connection) return

    // 连接状态事件
    this.connection.onreconnecting(() => {
      console.log('SignalR正在重连...')
      this.notifyConnectionStateChanged()
    })

    this.connection.onreconnected(() => {
      console.log('SignalR重连成功')
      this.reconnectAttempts = 0
      this.notifyConnectionStateChanged()
    })

    this.connection.onclose((error) => {
      console.log('SignalR连接已关闭', error)
      this.connection = null
      this.notifyConnectionStateChanged()
    })
  }

  private connectionStateCallbacks: (() => void)[] = []

  private notifyConnectionStateChanged(): void {
    this.connectionStateCallbacks.forEach(callback => callback())
  }

  // 发送消息
  async sendMessage(message: SendMessageRequest): Promise<void> {
    if (!this.connection) {
      throw new Error('SignalR连接未建立')
    }

    try {
      await this.connection.invoke('SendMessage', message)
    } catch (error) {
      console.error('发送消息失败:', error)
      throw error
    }
  }

  // 加入聊天室
  async joinChatRoom(chatRoomId: number): Promise<void> {
    if (!this.connection) {
      throw new Error('SignalR连接未建立')
    }

    try {
      await this.connection.invoke('JoinChatRoom', chatRoomId)
    } catch (error) {
      console.error('加入聊天室失败:', error)
      throw error
    }
  }

  // 离开聊天室
  async leaveChatRoom(chatRoomId: number): Promise<void> {
    if (!this.connection) {
      throw new Error('SignalR连接未建立')
    }

    try {
      await this.connection.invoke('LeaveChatRoom', chatRoomId)
    } catch (error) {
      console.error('离开聊天室失败:', error)
      throw error
    }
  }

  // 标记为已读
  async markAsRead(chatRoomId: number): Promise<void> {
    if (!this.connection) {
      throw new Error('SignalR连接未建立')
    }

    try {
      await this.connection.invoke('MarkAsRead', chatRoomId)
    } catch (error) {
      console.error('标记已读失败:', error)
      throw error
    }
  }

  // 开始输入
  async startTyping(chatRoomId: number): Promise<void> {
    if (!this.connection) return

    try {
      await this.connection.invoke('StartTyping', chatRoomId)
    } catch (error) {
      console.error('发送输入状态失败:', error)
    }
  }

  // 停止输入
  async stopTyping(chatRoomId: number): Promise<void> {
    if (!this.connection) return

    try {
      await this.connection.invoke('StopTyping', chatRoomId)
    } catch (error) {
      console.error('发送停止输入状态失败:', error)
    }
  }

  // 删除消息
  async deleteMessage(messageId: number): Promise<void> {
    if (!this.connection) {
      throw new Error('SignalR连接未建立')
    }

    try {
      await this.connection.invoke('DeleteMessage', messageId)
    } catch (error) {
      console.error('删除消息失败:', error)
      throw error
    }
  }

  // 编辑消息
  async editMessage(messageId: number, newContent: string): Promise<void> {
    if (!this.connection) {
      throw new Error('SignalR连接未建立')
    }

    try {
      await this.connection.invoke('EditMessage', messageId, newContent)
    } catch (error) {
      console.error('编辑消息失败:', error)
      throw error
    }
  }

  // 标记为已读
  async markAsRead(chatRoomId: number): Promise<void> {
    if (!this.connection) {
      throw new Error('SignalR连接未建立')
    }

    try {
      await this.connection.invoke('MarkAsRead', chatRoomId)
      console.log(`已调用 MarkAsRead，聊天室ID: ${chatRoomId}`)
    } catch (error) {
      console.error('标记已读失败:', error)
      throw error
    }
  }

  // 事件监听器注册方法
  onReceiveMessage(callback: (message: Message) => void): void {
    this.connection?.on('ReceiveMessage', callback)
  }

  onUserOnline(callback: (userId: number) => void): void {
    this.connection?.on('UserOnline', callback)
  }

  onUserOffline(callback: (userId: number) => void): void {
    this.connection?.on('UserOffline', callback)
  }

  onUserJoinedChatRoom(callback: (chatRoomId: number, userId: number) => void): void {
    this.connection?.on('UserJoinedChatRoom', callback)
  }

  onUserLeftChatRoom(callback: (chatRoomId: number, userId: number) => void): void {
    this.connection?.on('UserLeftChatRoom', callback)
  }

  onUserStartedTyping(callback: (chatRoomId: number, userId: number) => void): void {
    this.connection?.on('UserStartedTyping', callback)
  }

  onUserStoppedTyping(callback: (chatRoomId: number, userId: number) => void): void {
    this.connection?.on('UserStoppedTyping', callback)
  }

  onMessageDeleted(callback: (messageId: number) => void): void {
    this.connection?.on('MessageDeleted', callback)
  }

  onMessageEdited(callback: (message: Message) => void): void {
    this.connection?.on('MessageEdited', callback)
  }

  onError(callback: (error: string) => void): void {
    this.connection?.on('Error', callback)
  }

  onMarkedAsRead(callback: (chatRoomId: number) => void): void {
    this.connection?.on('MarkedAsRead', callback)
  }

  // 连接状态变化监听
  onConnectionStateChanged(callback: () => void): void {
    this.connectionStateCallbacks.push(callback)
  }

  // 移除事件监听器
  off(eventName: string): void {
    this.connection?.off(eventName)
  }

  // 获取连接状态
  get isConnected(): boolean {
    return this.connection?.state === 'Connected'
  }

  get connectionState(): string {
    return this.connection?.state || 'Disconnected'
  }
}

export const signalRService = new SignalRService()
export default signalRService
